home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / TKERN091.ZIP / SRC / FORMATTR.C next >
Text File  |  1994-03-01  |  14KB  |  711 lines

  1. /*
  2.  *  This file forms part of "TKERN" - "Troy's Kernel for Windows".
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* __formattr does formatted output. It is here to serve all the printf
  22.  * type functions. They call __formatter with the address of a function
  23.  * that __formatter will call when it has a character, and a void pointer
  24.  * which is passwd to that function as the first argument. The character
  25.  * is passed as the second argument.
  26.  *
  27.  * This function can be safely placed in the DLL without sacrificing
  28.  * portability. It basically means that this module can be under GNU
  29.  * Library License without compromising any other programs using the
  30.  * stubs (which are freely redistributable and usable for any purpose
  31.  * whatsoever).
  32.  *
  33.  * Note that this also makes it trivial to design new printf type
  34.  * functions without resorting to sprintf on a large string.
  35.  */
  36.  
  37. #include <stdlib.h>
  38. #include <stdarg.h>
  39. #include <string.h>
  40. #include <ctype.h>
  41. #include <float.h>
  42. #include <math.h>
  43.  
  44. #define    FLAG_SHOWSIGN    0x0001
  45. #define    FLAG_LEFT    0x0002
  46. #define    FLAG_ZEROES    0x0004
  47. #define    FLAG_BLANK    0x0008
  48. #define    FLAG_ALTERNATE    0x0010
  49. #define    FLAG_UPPER    0x0020
  50. #define    FLAG_EXPONENTIAL 0x0040
  51. #define    FLAG_MAYEXP    0x0080
  52.  
  53. #pragma warn -pls
  54.  
  55. static    char    buffer[1024];
  56.  
  57.  
  58. #pragma argsused
  59. static int
  60. show_integer(    int    (*func)(void *a, char b),
  61.         void    *func_arg,
  62.         char    const *pch,
  63.         char    cSign,
  64.         int    nWidth,
  65.         int    nPrec,
  66.         int    nFlags)
  67. {
  68.     char    cFill = ((nFlags & FLAG_ZEROES) ? '0' : ' ');
  69.     int    iLen;
  70.     int    nChars = 0;
  71.  
  72.     iLen = strlen(pch) + (cSign ? 1 : 0);
  73.     if (iLen > nWidth)
  74.         nWidth = iLen;
  75.     else if (nWidth > iLen &&
  76.          (!(nFlags & FLAG_LEFT) ||
  77.          (nFlags & FLAG_ZEROES)))
  78.     {
  79.         if (cFill == '0' && cSign)
  80.         {
  81.             (*func)(func_arg, cSign);
  82.             cSign = '\0';
  83.             iLen--;
  84.             nWidth--;
  85.             nChars++;
  86.         }
  87.         while (nWidth > iLen)
  88.         {
  89.             nWidth--;
  90.             nChars++;
  91.             (*func)(func_arg, cFill);
  92.         }
  93.     }
  94.     if (cSign)
  95.     {
  96.         (*func)(func_arg, cSign);
  97.         iLen--;
  98.         nWidth--;
  99.         nChars++;
  100.     }
  101.     while (iLen--)
  102.     {
  103.         nWidth--;
  104.         (*func)(func_arg, *pch++);
  105.         nChars++;
  106.     }
  107.     while (nWidth--)
  108.     {
  109.         (*func)(func_arg, ' ');
  110.         nChars++;
  111.     }
  112.     return nChars;
  113. }
  114.  
  115.  
  116. static int    
  117. show_long(    int    (*func)(void *a, char b),
  118.         void    *func_arg,
  119.         long    number,
  120.         int    nWidth,
  121.         int    nPrec,
  122.         int    nFlags)
  123. {
  124.     char    *pch = buffer;
  125.     char    cSign = '\0';
  126.     int    nLen;
  127.  
  128.     ltoa(number, buffer, 10);
  129.     if (*pch == '-')
  130.     {
  131.         cSign = '-';
  132.         pch++;
  133.     }
  134.     else if (nFlags & FLAG_SHOWSIGN)
  135.     {
  136.         cSign = '+';
  137.     }
  138.     else if (nFlags & FLAG_BLANK)
  139.     {
  140.         cSign = ' ';
  141.     }
  142.     return show_integer(func, func_arg, pch, cSign, nWidth, nPrec, nFlags);
  143. }
  144.         
  145. static int    
  146. show_ulong(    int    (*func)(void *a, char b),
  147.         void    *func_arg,
  148.         long    number,
  149.         int    nWidth,
  150.         int    nPrec,
  151.         int    nFlags)
  152. {
  153.     ultoa(number, buffer, 10);
  154.     return show_integer(func, func_arg, buffer, '\0', nWidth, nPrec, nFlags);
  155. }
  156.         
  157. static int    
  158. show_hex(    int    (*func)(void *a, char b),
  159.         void    *func_arg,
  160.         long    number,
  161.         int    nWidth,
  162.         int    nPrec,
  163.         int    nFlags)
  164. {
  165.     ultoa(number, buffer, 16);
  166.     if (nFlags & FLAG_UPPER)
  167.         strupr(buffer);
  168.     return show_integer(func, func_arg, buffer, '\0', nWidth, nPrec, nFlags);
  169. }
  170.  
  171. static    int
  172. show_real(    int    (*func)(void *a, char b),
  173.         void    *func_arg,
  174.         long double fValue,
  175.         int    nWidth,
  176.         int    nPrecision,
  177.         int    nFlags,
  178.         int    nDigits)
  179. {
  180.     int    aiDigits[LDBL_DIG + 1];
  181.     long    double    fMantissa;
  182.     int    nExponent;
  183.     int    nSign = 1;
  184.     int    nVisible;
  185.     char    achExponent[10];
  186.     int    nWritten = 0;
  187.     int    iLastDigit;
  188.     int    *piStart;
  189.     char    *pchStart;
  190.     int    i;
  191.  
  192.     if (fValue < 0)
  193.     {
  194.         nSign = -1;
  195.         fValue = -fValue;
  196.     }
  197.     if (fValue)
  198.         nExponent = floor(log10(fValue));
  199.     else
  200.         nExponent = 0;
  201.     fMantissa = fValue / pow(10, nExponent);
  202.  
  203.     aiDigits[0] = 0;
  204.     for (i = 1; i <= nDigits; i++)
  205.     {
  206.         if (fMantissa < 0) /* Rounding error */
  207.             fMantissa = 0;
  208.         aiDigits[i] = floor(fMantissa);
  209.         fMantissa = (fMantissa - aiDigits[i]) * 10;
  210.     }
  211.     for (; i < nDigits; i++)
  212.     {
  213.         aiDigits[i] = 0;
  214.     }
  215.     if (nPrecision == -1)
  216.         nPrecision = 6;
  217.     if (nFlags & FLAG_MAYEXP &&
  218.         nExponent >= 0 &&
  219.         nExponent +
  220.          (nPrecision ? nPrecision + 2 : 1) +
  221.          ((nSign == -1 || (nFlags & FLAG_SHOWSIGN)) ? 1 : 0) > nWidth)
  222.         nFlags |= FLAG_EXPONENTIAL;
  223.     if (nFlags & FLAG_EXPONENTIAL)
  224.     {
  225.         ltoa(nExponent, achExponent, 10);
  226.         nVisible = 1 + (nPrecision ? nPrecision + 2 : 1) + strlen(achExponent);
  227.     }
  228.     else
  229.     {
  230.         if (nExponent < 0)
  231.         {
  232.             nVisible = nPrecision ? nPrecision : 1;
  233.         }
  234.         else
  235.         {
  236.             nVisible = nExponent + (nPrecision ? nPrecision + 2 : 1);
  237.         }
  238.     }
  239.     if (nSign == -1 || nFlags & FLAG_SHOWSIGN)
  240.         nVisible++;
  241.     if (!(nFlags & FLAG_LEFT))
  242.     {
  243.         while (nVisible < nWidth--)
  244.         {
  245.             (*func)(func_arg, ' ');
  246.             nWritten++;
  247.         }
  248.     }
  249.  
  250.     if ((nFlags & FLAG_EXPONENTIAL) || nExponent < nDigits)
  251.     {
  252.         if ((nFlags & FLAG_EXPONENTIAL) || (nExponent < 0))
  253.         {
  254.             iLastDigit = 1 + nPrecision;
  255.         }
  256.         else
  257.         {
  258.             iLastDigit = 1 + nExponent + nPrecision;
  259.         }
  260.         if (iLastDigit < nDigits &&
  261.             aiDigits[iLastDigit+1] >= 5)
  262.         {
  263.             while (aiDigits[iLastDigit] == 9)
  264.                 aiDigits[iLastDigit--] = 0;
  265.             aiDigits[iLastDigit]++;
  266.         }
  267.     }
  268.  
  269.     if (nSign == -1)
  270.     {
  271.         (*func)(func_arg, '-');
  272.         nWritten++;
  273.     }
  274.     else if (nFlags & FLAG_SHOWSIGN)
  275.     {
  276.         (*func)(func_arg, '+');
  277.     }
  278.     if (aiDigits[0])
  279.     {
  280.         nExponent++;
  281.         piStart = aiDigits;
  282.     }
  283.     else
  284.     {
  285.         piStart = aiDigits + 1;
  286.     }
  287.     if (nFlags & FLAG_EXPONENTIAL)
  288.     {
  289.         (*func)(func_arg, '0' + *piStart++);
  290.         nWritten++;
  291.         if (nPrecision)
  292.         {
  293.             if (nPrecision > nDigits - 1)
  294.                 nPrecision = nDigits - 1;
  295.             (*func)(func_arg, '.');
  296.             nWritten++;
  297.             while(nPrecision--)
  298.             {
  299.                 (*func)(func_arg, '0' + *piStart++);
  300.                 nWritten++;
  301.             }
  302.             if (nFlags & FLAG_UPPER)
  303.                 (*func)(func_arg, 'E');
  304.             else
  305.                 (*func)(func_arg, 'e');
  306.             nWritten++;
  307.             for (pchStart = achExponent; *pchStart; pchStart++)
  308.             {
  309.                 (*func)(func_arg, *pchStart);
  310.                 nWritten++;
  311.             }
  312.         }
  313.     }
  314.     else
  315.     {
  316.         if (nExponent >= 0)
  317.         {
  318.             while (nExponent-- >= 0)
  319.             {
  320.                 if (nDigits-- > 0)
  321.                     (*func)(func_arg, '0' + *piStart++);
  322.                 else
  323.                     (*func)(func_arg, '0');
  324.                 nWritten++;
  325.             }
  326.             if (nPrecision)
  327.             {
  328.                 (*func)(func_arg, '.');
  329.                 nWritten++;
  330.             }
  331.         }
  332.         else
  333.         {
  334.             (*func)(func_arg, '0');
  335.             if (nPrecision)
  336.                 (*func)(func_arg, '.');
  337.             while (nExponent++ && nPrecision--)
  338.             {
  339.                 (*func)(func_arg, '0');
  340.                 nWritten++;
  341.             }
  342.         }
  343.         while (nPrecision-- > 0)
  344.         {
  345.             if (nDigits-- > 0)
  346.                 (*func)(func_arg, '0 ' + *piStart++);
  347.             else
  348.                 (*func)(func_arg, '0');
  349.             nWritten++;
  350.         }
  351.     }
  352.  
  353.     if (nFlags & FLAG_LEFT)
  354.     {
  355.         while (nVisible < nWidth--)
  356.         {
  357.             (*func)(func_arg, ' ');
  358.             nWritten++;
  359.         }
  360.     }
  361.  
  362.     return nWritten;
  363. }
  364.         
  365.  
  366. int far _export
  367. __formatter(    int    (*func)(void *a, char b),
  368.         void    *func_arg,
  369.         char    const *format,
  370.         va_list    arg)
  371. {
  372.     int    nChars = 0;
  373.     int    nPrecision;
  374.     int    nWidth;
  375.     int    nLong;
  376.     long    nIntValue;
  377.     int    nFlags;
  378.     int    nPad;
  379.     int    nLen;
  380.     union
  381.     {
  382.         short        nShort;
  383.         int        nInt;
  384.         long        nLong;
  385.         unsigned short    nUShort;
  386.         unsigned int    nUInt;
  387.         unsigned long    nULong;
  388.  
  389.         float        fFloat;
  390.         double        fDouble;
  391.         long double    fLongDouble;
  392.  
  393.         char        cChar;
  394.  
  395.         char        *pchString;
  396.  
  397.         void        *pvPointer;
  398.     } Value;
  399.         
  400.  
  401.     while (*format)
  402.     {
  403.         if (*format == '%')
  404.         {
  405.             if (*++format == '%')